#include "core/Application.h"
#include "core/Logger.h"
#include "device/DeviceManager.h"
#include "service/DataCollector.h"
#include "service/DataUploader.h"
#include "service/AlarmManager.h"
#include "service/DispatchService.h"
#include "web/WebServer.h"
#include "utils/Config.h"
#include "utils/make_unique.h"

#include <iostream>
#include <thread>
#include <atomic>
#include <chrono>
#include <csignal>
#include <cstdlib>
#include <string>
#include <algorithm>

namespace ems {
namespace core {

static std::atomic<bool> g_shutdown_requested{false};
static std::atomic<int> g_last_signal{0};

void signalHandler(int signal) {
    if (signal == SIGINT || signal == SIGTERM) {
        g_last_signal.store(signal, std::memory_order_relaxed);
        g_shutdown_requested.store(true, std::memory_order_relaxed);
    }
}

Application& Application::getInstance() {
    static Application instance;
    return instance;
}

bool Application::initialize(const std::string& configPath) {
    try {
        LOG_INFO("Initializing EMS application...");
        
        configPath_ = configPath;
        running_ = false;
        g_shutdown_requested.store(false, std::memory_order_relaxed);
        g_last_signal.store(0, std::memory_order_relaxed);

        std::signal(SIGINT, signalHandler);
        std::signal(SIGTERM, signalHandler);
        
        loadConfiguration(configPath);
        initializeModules();
        
        LOG_INFO("EMS application initialized successfully");
        return true;
        
    } catch (const std::exception& e) {
        LOG_ERROR("Failed to initialize application: " << e.what());
        return false;
    }
}

void Application::run() {
    if (running_) {
        LOG_WARN("Application is already running");
        return;
    }
    
    try {
        LOG_INFO("Starting EMS application...");
        
        startServices();
        running_ = true;
        
        LOG_INFO("EMS application started successfully");

        bool shutdownSignaled = false;

        while (running_) {
            if (g_shutdown_requested.load(std::memory_order_relaxed)) {
                if (!shutdownSignaled) {
                    const int sig = g_last_signal.load(std::memory_order_relaxed);
                    if (sig != 0) {
                        LOG_INFO("Shutdown signal " << sig << " received, initiating graceful shutdown...");
                    } else {
                        LOG_INFO("Shutdown requested, initiating graceful shutdown...");
                    }
                    shutdownSignaled = true;
                }
                requestShutdown();
            }

            if (!running_) {
                break;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        
        LOG_INFO("EMS application shutdown initiated");
        shutdown();
        
    } catch (const std::exception& e) {
        LOG_ERROR("Application runtime error: " << e.what());
        shutdown();
    }
}

void Application::shutdown() {
    if (!running_) {
        return;
    }
    
    LOG_INFO("Shutting down EMS application...");
    
    running_ = false;
    stopServices();
    
    // 额外清理步骤：确保所有web相关进程都被停止
    cleanupWebProcesses();
    
    LOG_INFO("EMS application shutdown completed");
}

void Application::requestShutdown() {
    running_ = false;
}

void Application::loadConfiguration(const std::string& configPath) {
    auto& config = utils::Config::getInstance();
    if (!config.load(configPath)) {
        throw std::runtime_error("Failed to load configuration from: " + configPath);
    }

    const auto& systemCfg = config.getSystem();

    auto toUpper = [](std::string value) {
        std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) {
            return static_cast<char>(std::toupper(c));
        });
        return value;
    };

    auto parseLevel = [&](const std::string& levelStr) -> LogLevel {
        const std::string upper = toUpper(levelStr);
        if (upper == "DEBUG") return LogLevel::DEBUG;
        if (upper == "INFO") return LogLevel::INFO;
        if (upper == "WARN" || upper == "WARNING") return LogLevel::WARN;
        if (upper == "ERROR") return LogLevel::ERROR;
        if (upper == "FATAL") return LogLevel::FATAL;
        return LogLevel::INFO;
    };

    Logger::getInstance().initialize(systemCfg.logFile, parseLevel(systemCfg.logLevel));
}

void Application::initializeModules() {
    deviceManager_ = ems::utils::make_unique<device::DeviceManager>();
    dataCollector_ = ems::utils::make_unique<service::DataCollector>();
    dataUploader_ = ems::utils::make_unique<service::DataUploader>();
    alarmManager_ = ems::utils::make_unique<service::AlarmManager>();
    dispatchService_ = ems::utils::make_unique<service::DispatchService>();
    // Initialize WebServer with config root so REST reads the correct files
    webServer_ = ems::utils::make_unique<web::WebServer>(9527, configPath_);
    
    if (!deviceManager_->initialize()) {
        throw std::runtime_error("Failed to initialize device manager");
    }
    
    if (!dataCollector_->initialize(deviceManager_.get())) {
        throw std::runtime_error("Failed to initialize data collector");
    }

    // 为数据上传器设置设备管理器引用（用于MQTT同步）
    dataUploader_->setDeviceManager(deviceManager_.get());

    if (!dataUploader_->initialize()) {
        throw std::runtime_error("Failed to initialize data uploader");
    }

    dispatchService_->setDataUploader(dataUploader_.get());

    // 设置数据采集器的回调函数，使用分类上报方式
    dataCollector_->setDataCallback([this](const std::string& deviceId, const std::vector<device::DataValue>& data) {
        LOG_INFO("分类数据回调触发 - 设备ID: " << deviceId << ", 数据点数量: " << data.size());
        // 改为“先赋值缓存”，由 DataUploader 按设备的 upload_interval 定时上报
        dataUploader_->updateSnapshot(deviceId, data);
    });

    dataCollector_->setErrorCallback([this](const std::string& deviceId, const std::string& error) {
        LOG_WARN("采集失败，暂停设备上报 - 设备ID: " << deviceId << ", 错误: " << error);
        dataUploader_->clearSnapshot(deviceId);
    });

    if (!alarmManager_->initialize()) {
        throw std::runtime_error("Failed to initialize alarm manager");
    }

    if (!dispatchService_->initialize()) {
        throw std::runtime_error("Failed to initialize dispatch service");
    }

    if (webServer_) {
        webServer_->setDispatchService(dispatchService_.get());
        webServer_->setDeviceManager(deviceManager_.get());
        webServer_->setDataCollector(dataCollector_.get());
        webServer_->setDataUploader(dataUploader_.get());
    }
}

void Application::startServices() {
    deviceManager_->start();
    dataCollector_->start();
    dataUploader_->start();
    alarmManager_->start();
    const auto& dispatchCfg = ems::utils::Config::getInstance().getDispatch();
    dispatchService_->setEnabled(dispatchCfg.enabled);
    dispatchService_->start();

    if (!webServer_->start()) {
        LOG_ERROR("Failed to start web server");
    }
}

void Application::stopServices() {
    if (webServer_) webServer_->stop();
    if (dispatchService_) dispatchService_->stop();
    if (alarmManager_) alarmManager_->stop();
    if (dataUploader_) dataUploader_->stop();
    if (dataCollector_) dataCollector_->stop();
    if (deviceManager_) deviceManager_->stop();
}

void Application::cleanupWebProcesses() {
    LOG_INFO("Performing additional cleanup for web processes...");
    
    // 使用系统命令强制停止占用web端口的进程
    const int webPorts[] = {9527, 8080, 8081, 8082};
    const int numPorts = sizeof(webPorts) / sizeof(webPorts[0]);
    
    for (int i = 0; i < numPorts; i++) {
        int port = webPorts[i];
        
        // 检查端口是否被占用
        std::string checkCmd = "lsof -ti:" + std::to_string(port) + " 2>/dev/null";
        FILE* pipe = popen(checkCmd.c_str(), "r");
        if (pipe != nullptr) {
            char buffer[256];
            if (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
                // 有进程占用端口，获取PID
                int pid = std::atoi(buffer);
                if (pid > 0) {
                    LOG_WARN("Port " << port << " is occupied by process " << pid << ", attempting to terminate...");
                    
                    // 先尝试温和的终止
                    std::string killCmd = "kill " + std::to_string(pid) + " 2>/dev/null";
                    int result = system(killCmd.c_str());
                    
                    // 等待一段时间让进程自然退出
                    std::this_thread::sleep_for(std::chrono::milliseconds(500));
                    
                    // 再次检查是否还在运行
                    FILE* checkPipe = popen(checkCmd.c_str(), "r");
                    if (checkPipe != nullptr) {
                        char checkBuffer[256];
                        if (fgets(checkBuffer, sizeof(checkBuffer), checkPipe) != nullptr) {
                            // 进程还在运行，强制杀死
                            LOG_WARN("Process " << pid << " still running, force killing...");
                            std::string forceKillCmd = "kill -9 " + std::to_string(pid) + " 2>/dev/null";
                            system(forceKillCmd.c_str());
                        }
                        pclose(checkPipe);
                    }
                }
            }
            pclose(pipe);
        }
    }
    
    LOG_INFO("Web process cleanup completed");
}

}  // namespace core
}  // namespace ems
